using Net35.Xrm.Sdk.Client;
using Net35.Xrm.Sdk.Metadata;
using Net35.Xrm.Sdk.Metadata.Query;
using Net35.Xrm.Sdk.Query;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Runtime.Serialization;
using System.Security;
namespace Net35.Xrm.Sdk
{
	internal static class KnownTypesProvider
	{
		private static object _lockObj;
		private static List<Assembly> _knownAssemblies;
		private static Dictionary<string, Type> _knownCustomValueTypes;
		private static bool _regenerateknownCustomValueTypes;
		private static Dictionary<string, Type> _knownOrganizationRequestResponseTypes;
		private static bool _regenerateknownOrganizationRequestResponseTypes;
		private static List<Assembly> KnownAssemblies
		{
			get
			{
				if (KnownTypesProvider._knownAssemblies == null)
				{
					lock (KnownTypesProvider._lockObj)
					{
						if (KnownTypesProvider._knownAssemblies == null)
						{
							KnownTypesProvider._knownAssemblies = new List<Assembly>();
							Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
							Assembly[] array = assemblies;
							for (int i = 0; i < array.Length; i++)
							{
								Assembly assembly = array[i];
								KnownTypesProvider.RegisterAssembly(assembly);
							}
						}
					}
				}
				return KnownTypesProvider._knownAssemblies;
			}
		}
		internal static Dictionary<string, Type> KnownCustomValueTypes
		{
			get
			{
				if (KnownTypesProvider._knownCustomValueTypes == null || KnownTypesProvider._regenerateknownCustomValueTypes)
				{
					lock (KnownTypesProvider._lockObj)
					{
						if (KnownTypesProvider._knownCustomValueTypes == null || KnownTypesProvider._regenerateknownCustomValueTypes)
						{
							List<Assembly> knownAssemblies = KnownTypesProvider.KnownAssemblies;
							Dictionary<string, Type> dictionary = new Dictionary<string, Type>();
							foreach (Assembly current in knownAssemblies)
							{
								if (!(current == Assembly.GetExecutingAssembly()))
								{
									ProxyTypesAssemblyAttribute proxyTypesAttribute = KnownTypesProvider.GetProxyTypesAttribute(current);
									if (proxyTypesAttribute != null && proxyTypesAttribute.ContainsSharedContracts)
									{
										Type[] exportedTypes = current.GetExportedTypes();
										for (int i = 0; i < exportedTypes.Length; i++)
										{
											Type type = exportedTypes[i];
											bool flag2 = false;
											object[] customAttributes = type.GetCustomAttributes(typeof(DataContractAttribute), false);
											if (customAttributes != null && customAttributes.Length > 0)
											{
												flag2 = true;
											}
											else
											{
												object[] customAttributes2 = type.GetCustomAttributes(typeof(CollectionDataContractAttribute), false);
												if (customAttributes2 != null && customAttributes2.Length > 0)
												{
													flag2 = true;
												}
											}
											if (flag2 && !type.IsSubclassOf(typeof(OrganizationRequest)) && !type.IsSubclassOf(typeof(OrganizationResponse)) && !dictionary.ContainsKey(type.Name))
											{
												dictionary.Add(type.Name, type);
												dictionary.Add(string.Format(CultureInfo.InvariantCulture, "ArrayOf{0}", new object[]
												{
													type.Name
												}), type.MakeArrayType());
												dictionary.Add(string.Format(CultureInfo.InvariantCulture, "ArrayOfArrayOf{0}", new object[]
												{
													type.Name
												}), type.MakeArrayType().MakeArrayType());
											}
										}
									}
								}
							}
							KnownTypesProvider._knownCustomValueTypes = dictionary;
							KnownTypesProvider._regenerateknownCustomValueTypes = false;
						}
					}
				}
				return KnownTypesProvider._knownCustomValueTypes;
			}
		}
		internal static Dictionary<string, Type> KnownOrganizationRequestResponseTypes
		{
			get
			{
				if (KnownTypesProvider._knownOrganizationRequestResponseTypes == null || KnownTypesProvider._regenerateknownOrganizationRequestResponseTypes)
				{
					lock (KnownTypesProvider._lockObj)
					{
						if (KnownTypesProvider._knownOrganizationRequestResponseTypes == null || KnownTypesProvider._regenerateknownOrganizationRequestResponseTypes)
						{
							List<Assembly> knownAssemblies = KnownTypesProvider.KnownAssemblies;
							Dictionary<string, Type> dictionary = new Dictionary<string, Type>();
							foreach (Assembly current in knownAssemblies)
							{
								Type[] exportedTypes = current.GetExportedTypes();
								for (int i = 0; i < exportedTypes.Length; i++)
								{
									Type type = exportedTypes[i];
									object[] customAttributes = type.GetCustomAttributes(typeof(DataContractAttribute), false);
									if (customAttributes != null && customAttributes.Length > 0 && (type.IsSubclassOf(typeof(OrganizationRequest)) || type.IsSubclassOf(typeof(OrganizationResponse))))
									{
										object[] array = customAttributes;
										for (int j = 0; j < array.Length; j++)
										{
											DataContractAttribute dataContractAttribute = (DataContractAttribute)array[j];
											string key = KnownTypesProvider.QualifiedName(dataContractAttribute.Name ?? type.Name, dataContractAttribute.Namespace);
											if (!dictionary.ContainsKey(key))
											{
												dictionary.Add(key, type);
											}
										}
									}
								}
							}
							KnownTypesProvider._knownOrganizationRequestResponseTypes = dictionary;
							KnownTypesProvider._regenerateknownOrganizationRequestResponseTypes = false;
						}
					}
				}
				return KnownTypesProvider._knownOrganizationRequestResponseTypes;
			}
		}
		[SecuritySafeCritical]
		static KnownTypesProvider()
		{
			KnownTypesProvider._lockObj = new object();
			KnownTypesProvider._knownAssemblies = null;
			KnownTypesProvider._knownCustomValueTypes = null;
			KnownTypesProvider._regenerateknownCustomValueTypes = false;
			KnownTypesProvider._knownOrganizationRequestResponseTypes = null;
			KnownTypesProvider._regenerateknownOrganizationRequestResponseTypes = false;
			AppDomain.CurrentDomain.AssemblyLoad += new AssemblyLoadEventHandler(KnownTypesProvider.CurrentDomain_AssemblyLoad);
		}
		private static void CurrentDomain_AssemblyLoad(object sender, AssemblyLoadEventArgs args)
		{
			KnownTypesProvider.RegisterAssembly(args.LoadedAssembly);
		}
		private static void RegisterAssembly(Assembly assembly)
		{
			if (KnownTypesProvider.GetProxyTypesAttribute(assembly) == null)
			{
				return;
			}
			if (KnownTypesProvider.KnownAssemblies.Contains(assembly))
			{
				return;
			}
			lock (KnownTypesProvider._lockObj)
			{
				if (!KnownTypesProvider._knownAssemblies.Contains(assembly))
				{
					KnownTypesProvider._knownAssemblies.Add(assembly);
					KnownTypesProvider._regenerateknownCustomValueTypes = true;
					KnownTypesProvider._regenerateknownOrganizationRequestResponseTypes = true;
				}
			}
		}
		private static ProxyTypesAssemblyAttribute GetProxyTypesAttribute(Assembly assembly)
		{
			object[] customAttributes = assembly.GetCustomAttributes(typeof(ProxyTypesAssemblyAttribute), false);
			if (customAttributes == null || customAttributes.Length == 0)
			{
				return null;
			}
			return customAttributes[0] as ProxyTypesAssemblyAttribute;
		}
		public static IEnumerable<Type> RetrieveKnownValueTypes()
		{
			List<Type> list = new List<Type>();
			KnownTypesProvider.AddKnownAttributeTypes(list);
			list.Add(typeof(AliasedValue));
			list.Add(typeof(Dictionary<string, string>));
			list.Add(typeof(Entity));
			list.Add(typeof(Entity[]));
			list.Add(typeof(ColumnSet));
			list.Add(typeof(EntityReferenceCollection));
			list.Add(typeof(QueryBase));
			list.Add(typeof(QueryExpression));
			list.Add(typeof(QueryExpression[]));
			list.Add(typeof(LocalizedLabel[]));
			list.Add(typeof(PagingInfo));
			list.Add(typeof(Relationship));
			list.Add(typeof(AttributePrivilegeCollection));
			list.Add(typeof(RelationshipQueryCollection));
			list.Add(typeof(EntityMetadataCollection));
			list.Add(typeof(MetadataFilterExpression));
			list.Add(typeof(MetadataConditionExpression));
			list.Add(typeof(MetadataQueryBase));
			list.Add(typeof(DeletedMetadataFilters));
			list.Add(typeof(DeletedMetadataCollection));
			list.Add(typeof(ExecuteMultipleSettings));
			list.Add(typeof(OrganizationRequestCollection));
			list.Add(typeof(ExecuteMultipleResponseItemCollection));
			list.Add(typeof(QuickFindResultCollection));
			list.Add(typeof(QuickFindConfigurationCollection));
			Dictionary<string, Type> knownCustomValueTypes = KnownTypesProvider.KnownCustomValueTypes;
			foreach (Type current in knownCustomValueTypes.Values)
			{
				list.Add(current);
			}
			return list;
		}
		public static IEnumerable<Type> RetrieveKnownConditionValueTypes()
		{
			List<Type> list = new List<Type>();
			KnownTypesProvider.AddKnownAttributeTypes(list);
			return list;
		}
		internal static void AddKnownAttributeTypes(List<Type> knownTypes)
		{
			knownTypes.Add(typeof(bool));
			knownTypes.Add(typeof(bool[]));
			knownTypes.Add(typeof(int));
			knownTypes.Add(typeof(int[]));
			knownTypes.Add(typeof(string));
			knownTypes.Add(typeof(string[]));
			knownTypes.Add(typeof(string[][]));
			knownTypes.Add(typeof(double));
			knownTypes.Add(typeof(double[]));
			knownTypes.Add(typeof(decimal));
			knownTypes.Add(typeof(decimal[]));
			knownTypes.Add(typeof(Guid));
			knownTypes.Add(typeof(Guid[]));
			knownTypes.Add(typeof(DateTime));
			knownTypes.Add(typeof(DateTime[]));
			knownTypes.Add(typeof(Money));
			knownTypes.Add(typeof(Money[]));
			knownTypes.Add(typeof(EntityReference));
			knownTypes.Add(typeof(EntityReference[]));
			knownTypes.Add(typeof(OptionSetValue));
			knownTypes.Add(typeof(OptionSetValue[]));
			knownTypes.Add(typeof(EntityCollection));
			knownTypes.Add(typeof(Money));
			knownTypes.Add(typeof(Label));
			knownTypes.Add(typeof(LocalizedLabel));
			knownTypes.Add(typeof(LocalizedLabelCollection));
			knownTypes.Add(typeof(EntityMetadata[]));
			knownTypes.Add(typeof(EntityMetadata));
			knownTypes.Add(typeof(AttributeMetadata[]));
			knownTypes.Add(typeof(AttributeMetadata));
			knownTypes.Add(typeof(RelationshipMetadataBase[]));
			knownTypes.Add(typeof(RelationshipMetadataBase));
			knownTypes.Add(typeof(EntityFilters));
			knownTypes.Add(typeof(OptionSetMetadataBase));
			knownTypes.Add(typeof(OptionSetMetadataBase[]));
			knownTypes.Add(typeof(OptionSetMetadata));
			knownTypes.Add(typeof(BooleanOptionSetMetadata));
			knownTypes.Add(typeof(OptionSetType));
			knownTypes.Add(typeof(ManagedPropertyMetadata));
			knownTypes.Add(typeof(ManagedPropertyMetadata[]));
			knownTypes.Add(typeof(BooleanManagedProperty));
			knownTypes.Add(typeof(AttributeRequiredLevelManagedProperty));
		}
		public static List<Type> GetKnownMetadataEnumTypes()
		{
			return new List<Type>
			{
				typeof(object[]),
				typeof(StringFormat),
				typeof(StringFormat[]),
				typeof(AttributeRequiredLevel),
				typeof(AttributeRequiredLevel[]),
				typeof(AttributeTypeCode),
				typeof(AttributeTypeCode[]),
				typeof(CascadeType),
				typeof(CascadeType[]),
				typeof(Net35.Xrm.Sdk.Metadata.DateTimeFormat),
				typeof(Net35.Xrm.Sdk.Metadata.DateTimeFormat[]),
				typeof(IntegerFormat),
				typeof(IntegerFormat[]),
				typeof(ManagedPropertyEvaluationPriority),
				typeof(ManagedPropertyEvaluationPriority[]),
				typeof(ManagedPropertyOperation),
				typeof(ManagedPropertyOperation[]),
				typeof(ManagedPropertyType),
				typeof(ManagedPropertyType[]),
				typeof(SecurityTypes),
				typeof(SecurityTypes[]),
				typeof(OwnershipTypes),
				typeof(OwnershipTypes[]),
				typeof(ImeMode),
				typeof(ImeMode[]),
				typeof(RelationshipType),
				typeof(RelationshipType[])
			};
		}
		internal static string QualifiedName(string typeName, string typeNamespace)
		{
			return string.Format(CultureInfo.InvariantCulture, "{0}/{1}", new object[]
			{
				typeNamespace,
				typeName
			});
		}
	}
}
